
pub(crate) mod genpass;
pub(crate) mod csv;

pub(crate) mod base64;

pub(crate) mod text;
pub(crate) mod http;

use std::path::{Path, PathBuf};

use clap::Parser;

use crate::cli::text::{TextSubCommand};

use self::{csv::OutputFormat,csv::CsvOpts,
           genpass::{GenPassOpts},
           base64::{Base64SubCommand},
           http::{HttpSubCommand}
        };


#[derive(Debug, Parser)]
#[command(name = "rcli" , version,author,about,long_about = None)]
pub struct Opts {
    #[command(subcommand)]
    pub cmd: SubCommand,
}

#[derive(Debug, Parser)]
pub enum SubCommand {
    #[command(name = "csv", about = "show CSV  , or cover CSV  to other format")]
    Csv(CsvOpts),
    // 生成随机 密码的 命令
    #[command(name = "genpass", about = "generate random password")]
    GenPass(GenPassOpts),

    // Base64 编码 和 解码, command 里嵌套 command
    #[command(subcommand)]
    Base64(Base64SubCommand),

    // Text  签名 和 验证
    #[command(subcommand)]
    Text(TextSubCommand),

    #[command(subcommand)]
    Http(HttpSubCommand),
 
}



fn verify_input_filename(filename: &str) -> Result<String, &'static str> {

    if filename == "-" || Path::new(filename).exists() {
        Ok(filename.to_string())
    } else {
    //    Err(format!("Input file {} does not exist", filename))
        Err("Input file does not exist")
    }
}

// check if the path is exist
// pub fn verify_path(path: &str) -> Result<String, String> {

//     if  Path::new(path).exists() {
//         Ok(path.to_string())
//     } else {
//         // let msg = format!("Input file {} does not exist", path);
//         // let msg = &msg.as_str();
//         // Err(msg)
//         Err(format!("Input path {} does not exist",path))
//     }
// }

fn verify_path(path: &str) -> Result<PathBuf, &'static str> {
    // if input is "-" or file exists
    let p = Path::new(path);
    if p.exists() && p.is_dir() {
        Ok(path.into())
    } else {
        Err("Path does not exist or is not a directory")
    }
}


fn verify_format(format: &str) -> Result<OutputFormat, anyhow::Error> {

    format.parse::<OutputFormat>()
 }

 
// 实现 从 OutputFormat 到 &str 的转换 , 即 OutputFormat::Json  -> "json"
impl From<OutputFormat> for &'static  str {
    fn from(format: OutputFormat) -> Self {
        match format {
            OutputFormat::Json => "json",
            OutputFormat::Yaml => "yaml",
            OutputFormat::Toml => "toml",
         //   OutputFormat::Xml => "xml",
          //  OutputFormat::Csv => "csv",
        }
    }
}


#[cfg(test)]  // 编译的宏， 只在 测试时 编译
mod tests{
    use super::*;
    #[test]
    fn test_verify_input_filename() {
        


        assert_eq!(verify_input_filename("non_existent_file.txt"), Err("Input file does not exist"));
        assert_eq!(verify_input_filename("-"), Ok("-".to_string()));
        assert_eq!(verify_input_filename("-"), Ok("-".into()));
        // 这里假设 "Cargo.toml" 文件存在
        assert_eq!(verify_input_filename("Cargo.toml"), Ok("Cargo.toml".to_string()));
    }

    // #[test]
    // fn test_verify_format() {
    //     assert_eq!(verify_format("json").unwrap(), OutputFormat::Json);
    //     assert_eq!(verify_format("yaml").unwrap(), OutputFormat::Yaml);
    //     assert_eq!(verify_format("toml").unwrap(), OutputFormat::Toml);
    //     assert!(verify_format("xml").is_err());
    // }
}

